package com.run_java_test.test_run;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

@RequestMapping("up")
@RestController
public class UploadCodeController {

    private static final String SOURCE_DIR = "dynamic_sources";
    private static final String OUTPUT_DIR = "dynamic_classes";

    @Autowired
    private GenericApplicationContext applicationContext;


    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    private <T> void registerControllerBean(@NotNull Class<T> clazz) {
        String beanName = clazz.getSimpleName() + "_" + System.currentTimeMillis();

        // 动态注册 Bean
        T controllerInstance;
        try {
            controllerInstance = clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("无法实例化动态 Controller 类", e);
        }

        applicationContext.registerBean(beanName, clazz, () -> controllerInstance);

        // 刷新 HandlerMapping 以加载新注册的 Controller
        try {
            handlerMapping.afterPropertiesSet();
        } catch (Exception e) {
            throw new RuntimeException("刷新 HandlerMapping 时出错", e);
        }
    }

    public UploadCodeController() throws IOException {
        Files.createDirectories(Paths.get(SOURCE_DIR));
        Files.createDirectories(Paths.get(OUTPUT_DIR));
    }

    @PostMapping("/upload")
    public String uploadAndCompile(@RequestParam("file") MultipartFile file) throws Exception {
        // 保存文件到临时目录
        String fileName = file.getOriginalFilename();
        if (fileName == null || !fileName.endsWith(".java")) {
            throw new IllegalArgumentException("仅支持 .java 文件");
        }

        Path sourcePath = Paths.get(SOURCE_DIR, fileName);
        Files.write(sourcePath, file.getBytes());

        // 动态编译文件
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(sourcePath.toFile());

        // 设置编译输出目录
        List<String> options = Arrays.asList("-d", OUTPUT_DIR);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, compilationUnits);

        if (!task.call()) {
            throw new RuntimeException("编译失败，请检查源代码！");
        }

        fileManager.close();

        // 动态加载类
        String className = fileName.replace(".java", "");
        URLClassLoader classLoader = new URLClassLoader(
                new URL[]{new File(OUTPUT_DIR).toURI().toURL()},
                this.getClass().getClassLoader());
        Class<?> clazz = classLoader.loadClass(className);

        // 动态注册为 Spring Bean
        registerControllerBean(clazz);

        return "编译成功并注册为 Controller，类名: " + className;
    }

}
